﻿using System;
using NazTek.Utility.Extensions.SimpleType;

namespace NazTek.Utility
{
    /// <summary> 
    /// Allows value or key/value attributes to be placed in attributable context 
    /// </summary> 
    /// <remarks>The class may be used to associate additional attributes with fields, properties, and methods of types, such as, enum, class, structure, etc.</remarks> 
    /// <example>Samples below show how to use the class with enum fields.
    /// <code>
    /// internal enum Gender
    /// {
    ///     [Description("M")]
    ///     Male,
    ///     [Description("F")]
    ///     Female
    /// }
    /// 
    /// internal enum AgeGroup : short
    /// {
    ///     [Description("MinAge", "18")]
    ///     [Description("MaxAge", "35")]
    ///     [Description("Ages 18 to 35")]
    ///     Young,
    ///     [Description("MinAge", "36")]
    ///     [Description("MaxAge", "65")]
    ///     [Description("Ages 36 to 65")]
    ///     MiddleAged,
    ///     [Description("MinAge", "66")]
    ///     [Description("MaxAge", "100")]
    ///     [Description("Ages 66 to 100")]
    ///     Elder
    /// }
    /// </code>
    /// </example>
    /// <seealso cref="EnumExtension"/>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = true)]
    public sealed class DescriptionAttribute : Attribute
    {
        /// <summary> 
        /// The key of a key/value pair attribute 
        /// </summary> 
        /// <remarks>The class targets enumerations but may be used in any context, if appropriate</remarks> 
        private readonly string _descriptionId;
        /// <summary> 
        /// The value of either a key/value pair or just value attribute 
        /// </summary> 
        /// <remarks></remarks> 
        private readonly string _descriptionText;

        /// <summary> 
        /// Gets the description id
        /// </summary> 
        /// <value>Description id</value> 
        /// <returns>The key</returns> 
        /// <remarks></remarks> 
        public string DescriptionId
        {
            get { return _descriptionId; }
        }
        /// <summary> 
        /// Gets the description
        /// </summary> 
        /// <value>Assigned description</value> 
        /// <returns>The value</returns> 
        /// <remarks></remarks> 
        public string DescriptionText
        {
            get { return _descriptionText; }
        }
        /// <summary>
        /// Gets whether the description has an associated key
        /// </summary>
        public bool HasKey { get { return !string.IsNullOrWhiteSpace(DescriptionId); } }

        /// <summary> 
        /// Creates a description text instance 
        /// </summary> 
        /// <param name="descriptionText">The value of the value</param> 
        /// <remarks></remarks> 
        /// <example>Samples below show how to use the class with enum fields.
        /// <code>
        /// internal enum Gender
        /// {
        ///     [Description("M")]
        ///     Male,
        ///     [Description("F")]
        ///     Female
        /// }
        /// </code>
        /// </example>
        public DescriptionAttribute(string descriptionText)
        {
            this._descriptionText = descriptionText;
        }
        /// <summary> 
        /// Creates a key/value instance 
        /// </summary> 
        /// <param name="descriptionId">Key of the key/value pair</param> 
        /// <param name="descriptionText">Value of the key/value pair</param> 
        /// <remarks></remarks> 
        /// <example>Samples below show how to use the class with enum fields.
        /// <code>
        /// internal enum AgeGroup : short
        /// {
        ///     [Description("MinAge", "18")]
        ///     [Description("MaxAge", "35")]
        ///     [Description("Ages 18 to 35")]
        ///     Young,
        ///     [Description("MinAge", "36")]
        ///     [Description("MaxAge", "65")]
        ///     [Description("Ages 36 to 65")]
        ///     MiddleAged,
        ///     [Description("MinAge", "66")]
        ///     [Description("MaxAge", "100")]
        ///     [Description("Ages 66 to 100")]
        ///     Elder
        /// }
        /// </code>
        /// </example>
        public DescriptionAttribute(string descriptionId, string descriptionText)
            : this(descriptionText)
        {
            this._descriptionId = descriptionId;
        }
    }
}